package com.lonely.goods.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lonely.common.core.domain.BaseEntity;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.goods.domain.dto.goods.GoodsQuotationSheetPartDTO;
import com.lonely.goods.domain.dto.goods.GoodsQuotationSheetPartSecondProcessDTO;
import com.lonely.goods.domain.dto.goods.GoodsQuotationSheetSubmitDTO;
import com.lonely.goods.domain.entity.SysGoodsSecondProcess;
import com.lonely.goods.enums.GoodsEnum;
import com.lonely.goods.mapper.SysGoodsSecondProcessMapper;
import com.lonely.goods.service.IGoodsSecondProcessService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : 黄志标
 * @date: 2025/7/2 10:45
 * @description: 商品二次工艺服务实现类
 */
@Service
public class GoodsSecondProcessServiceImpl extends ServiceImpl<SysGoodsSecondProcessMapper, SysGoodsSecondProcess> implements IGoodsSecondProcessService {

    /**
     * 编辑商品报价单部件二次工艺信息
     *
     * @param submitDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitGoodsQuotationSheetPartsSecondProcess(GoodsQuotationSheetSubmitDTO submitDTO) {

        if (CollUtil.isEmpty(submitDTO.getParts())) {
            return;
        }

        for (GoodsQuotationSheetPartDTO part : submitDTO.getParts()) {

            // 获取数据库中当前paratId对应的二次工艺数据
            List<SysGoodsSecondProcess> existsGoodsSecondProcesses = super.list(new LambdaQueryWrapper<SysGoodsSecondProcess>()
                    .eq(SysGoodsSecondProcess::getGoodsId, submitDTO.getId())
                    .eq(SysGoodsSecondProcess::getGoodsPartId, part.getPartId())
                    .eq(SysGoodsSecondProcess::getType, GoodsEnum.GoodsSecondProcessTypeEnum.DOUGH_AND_AUXILIARY_MATERIALS.getType())
            );
            List<Long> existsGoodsSecondProcessIds = existsGoodsSecondProcesses.stream().map(BaseEntity::getId).filter(Objects::nonNull).collect(Collectors.toList());

            // 添加的二次工艺数据
            List<GoodsQuotationSheetPartSecondProcessDTO> submitSecondProcesses = Optional.ofNullable(part.getPartSecondProcesses()).orElse(new ArrayList<>());
            List<Long> submitGoodsSecondProcessIds = submitSecondProcesses.stream().map(GoodsQuotationSheetPartSecondProcessDTO::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList());


            // 找到待新增的数据
            List<GoodsQuotationSheetPartSecondProcessDTO> needAddGoodsSps = submitSecondProcesses.stream().filter(x -> x.getId() == null).collect(Collectors.toList());

            // 找到待删除的数据
            List<Long> needRemoveGoodsSecondProcessIds = existsGoodsSecondProcessIds.stream().filter(x -> !submitGoodsSecondProcessIds.contains(x)).distinct().collect(Collectors.toList());

            // 找到待更新的数据
            List<Long> needUpdateGoodsSecondProcessIds = existsGoodsSecondProcessIds.stream().filter(submitGoodsSecondProcessIds::contains).distinct().collect(Collectors.toList());


            if (CollUtil.isNotEmpty(needAddGoodsSps)) {
                List<SysGoodsSecondProcess> needAddGspList = needAddGoodsSps.stream().map(x -> {
                    SysGoodsSecondProcess sysGoodsSecondProcess = new SysGoodsSecondProcess();
                    BeanUtils.copyProperties(x, sysGoodsSecondProcess);
                    sysGoodsSecondProcess.setGoodsId(submitDTO.getId());
                    sysGoodsSecondProcess.setGoodsPartId(part.getPartId());
                    sysGoodsSecondProcess.setType(GoodsEnum.GoodsSecondProcessTypeEnum.DOUGH_AND_AUXILIARY_MATERIALS.getType());
                    sysGoodsSecondProcess.setCreateBy(SecurityUtils.getUserId());
                    sysGoodsSecondProcess.setUpdateBy(SecurityUtils.getUserId());
                    return sysGoodsSecondProcess;
                }).collect(Collectors.toList());

                super.saveBatch(needAddGspList);
            }

            if (CollUtil.isNotEmpty(needRemoveGoodsSecondProcessIds)) {
                super.removeByIds(needRemoveGoodsSecondProcessIds);
            }

            if (CollUtil.isNotEmpty(needUpdateGoodsSecondProcessIds)) {
                Map<Long, GoodsQuotationSheetPartSecondProcessDTO> submitGoodsSpMap = submitSecondProcesses.stream().filter(x -> needUpdateGoodsSecondProcessIds.contains(x.getId()))
                        .collect(Collectors.toMap(GoodsQuotationSheetPartSecondProcessDTO::getId, Function.identity(), (a, b) -> b));
                List<SysGoodsSecondProcess> needUpdateGoodsSpModels = existsGoodsSecondProcesses.stream().filter(x -> needUpdateGoodsSecondProcessIds.contains(x.getId()))
                        .peek(x -> {
                            GoodsQuotationSheetPartSecondProcessDTO submitGoodsSp = submitGoodsSpMap.get(x.getId());
                            BeanUtils.copyProperties(submitGoodsSp, x);
                        }).collect(Collectors.toList());
                super.updateBatchById(needUpdateGoodsSpModels);
            }

        }
    }

    /**
     * 编辑商品报价单部件成衣二次工艺信息
     *
     * @param submitDTO
     */
    @Override
    public void submitGoodsQuotationSheetPartsReadyToWearSecondProcess(GoodsQuotationSheetSubmitDTO submitDTO) {
        if (CollUtil.isEmpty(submitDTO.getParts())) {
            return;
        }

        for (GoodsQuotationSheetPartDTO part : submitDTO.getParts()) {

            // 获取数据库中当前paratId对应的成衣二次工艺数据
            List<SysGoodsSecondProcess> existsGoodsSecondProcesses = super.list(new LambdaQueryWrapper<SysGoodsSecondProcess>()
                    .eq(SysGoodsSecondProcess::getGoodsId, submitDTO.getId())
                    .eq(SysGoodsSecondProcess::getGoodsPartId, part.getPartId())
                    .eq(SysGoodsSecondProcess::getType, GoodsEnum.GoodsSecondProcessTypeEnum.READY_TO_WEAR.getType())
            );
            List<Long> existsGoodsSecondProcessIds = existsGoodsSecondProcesses.stream().map(BaseEntity::getId).filter(Objects::nonNull).collect(Collectors.toList());

            // 添加的二次工艺数据
            List<GoodsQuotationSheetPartSecondProcessDTO> submitSecondProcesses = Optional.ofNullable(part.getPartReadyToWearSecondProcesses()).orElse(new ArrayList<>());
            List<Long> submitGoodsSecondProcessIds = submitSecondProcesses.stream().map(GoodsQuotationSheetPartSecondProcessDTO::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList());


            // 找到待新增的数据
            List<GoodsQuotationSheetPartSecondProcessDTO> needAddGoodsSps = submitSecondProcesses.stream().filter(x -> x.getId() == null).collect(Collectors.toList());

            // 找到待删除的数据
            List<Long> needRemoveGoodsSecondProcessIds = existsGoodsSecondProcessIds.stream().filter(x -> !submitGoodsSecondProcessIds.contains(x)).distinct().collect(Collectors.toList());

            // 找到待更新的数据
            List<Long> needUpdateGoodsSecondProcessIds = existsGoodsSecondProcessIds.stream().filter(submitGoodsSecondProcessIds::contains).distinct().collect(Collectors.toList());


            if (CollUtil.isNotEmpty(needAddGoodsSps)) {
                List<SysGoodsSecondProcess> needAddGspList = needAddGoodsSps.stream().map(x -> {
                    SysGoodsSecondProcess sysGoodsSecondProcess = new SysGoodsSecondProcess();
                    BeanUtils.copyProperties(x, sysGoodsSecondProcess);
                    sysGoodsSecondProcess.setGoodsId(submitDTO.getId());
                    sysGoodsSecondProcess.setGoodsPartId(part.getPartId());
                    sysGoodsSecondProcess.setType(GoodsEnum.GoodsSecondProcessTypeEnum.READY_TO_WEAR.getType());
                    sysGoodsSecondProcess.setCreateBy(SecurityUtils.getUserId());
                    sysGoodsSecondProcess.setUpdateBy(SecurityUtils.getUserId());
                    return sysGoodsSecondProcess;
                }).collect(Collectors.toList());

                super.saveBatch(needAddGspList);
            }

            if (CollUtil.isNotEmpty(needRemoveGoodsSecondProcessIds)) {
                super.removeByIds(needRemoveGoodsSecondProcessIds);
            }

            if (CollUtil.isNotEmpty(needUpdateGoodsSecondProcessIds)) {
                Map<Long, GoodsQuotationSheetPartSecondProcessDTO> submitGoodsSpMap = submitSecondProcesses.stream().filter(x -> needUpdateGoodsSecondProcessIds.contains(x.getId()))
                        .collect(Collectors.toMap(GoodsQuotationSheetPartSecondProcessDTO::getId, Function.identity(), (a, b) -> b));
                List<SysGoodsSecondProcess> needUpdateGoodsSpModels = existsGoodsSecondProcesses.stream().filter(x -> needUpdateGoodsSecondProcessIds.contains(x.getId()))
                        .peek(x -> {
                            GoodsQuotationSheetPartSecondProcessDTO submitGoodsSp = submitGoodsSpMap.get(x.getId());
                            BeanUtils.copyProperties(submitGoodsSp, x);
                        }).collect(Collectors.toList());
                super.updateBatchById(needUpdateGoodsSpModels);
            }

        }
    }

    /**
     * 查询商品报价单部件二次工艺信息
     *
     * @param partId
     * @return
     */
    @Override
    public List<GoodsQuotationSheetPartSecondProcessDTO> queryQuotationSheetPartSecondProcesses(Long partId) {
        return super.list(new LambdaQueryWrapper<SysGoodsSecondProcess>()
                .eq(SysGoodsSecondProcess::getGoodsPartId, partId)
                .eq(SysGoodsSecondProcess::getType, GoodsEnum.GoodsSecondProcessTypeEnum.DOUGH_AND_AUXILIARY_MATERIALS.getType())
        ).stream().map(this::convertSysGoodsProcess2GoodsQuotationSheetPartSecondProcessDTO).collect(Collectors.toList());
    }

    /**
     * 查询商品报价单部件成衣二次工艺信息
     *
     * @param partId
     * @return
     */
    @Override
    public List<GoodsQuotationSheetPartSecondProcessDTO> queryQuotationSheetPartReadyToWearSecondProcesses(Long partId) {
        return super.list(new LambdaQueryWrapper<SysGoodsSecondProcess>()
                .eq(SysGoodsSecondProcess::getGoodsPartId, partId)
                .eq(SysGoodsSecondProcess::getType, GoodsEnum.GoodsSecondProcessTypeEnum.READY_TO_WEAR.getType())
        ).stream().map(this::convertSysGoodsProcess2GoodsQuotationSheetPartSecondProcessDTO).collect(Collectors.toList());
    }

    /**
     * 获取指定商品id对应的 面辅料二次工艺信息
     *
     * @param goodsId
     * @return
     */
    @Override
    public List<SysGoodsSecondProcess> queryGoodsSecondProcesses(Long goodsId) {
        return super.list(new LambdaQueryWrapper<SysGoodsSecondProcess>()
                .eq(SysGoodsSecondProcess::getGoodsId, goodsId)
                .eq(SysGoodsSecondProcess::getType, GoodsEnum.GoodsSecondProcessTypeEnum.DOUGH_AND_AUXILIARY_MATERIALS.getType())
        );
    }

    /**
     * SysGoodsSecondProcess 转换成 GoodsQuotationSheetPartSecondProcessDTO 对象
     *
     * @param sysGoodsSecondProcess
     * @return
     */
    private GoodsQuotationSheetPartSecondProcessDTO convertSysGoodsProcess2GoodsQuotationSheetPartSecondProcessDTO(SysGoodsSecondProcess sysGoodsSecondProcess) {
        GoodsQuotationSheetPartSecondProcessDTO partSecondProcessDTO = new GoodsQuotationSheetPartSecondProcessDTO();
        BeanUtils.copyProperties(sysGoodsSecondProcess, partSecondProcessDTO);

        BigDecimal amount = NumberUtil.mul(
                NumberUtil.round(StrUtil.blankToDefault(sysGoodsSecondProcess.getUnitPrice(), "0"), 2),
                NumberUtil.round(StrUtil.blankToDefault(sysGoodsSecondProcess.getSimpleUse(), "0"), 2)
        );
        amount = NumberUtil.round(amount, 2);
        partSecondProcessDTO.setAmount(amount.toPlainString());
        return partSecondProcessDTO;
    }

}
